﻿/*
 * new.h
 */
#ifndef __GDK_NEW_H__
#define __GDK_NEW_H__

#include <gdk/core/Types.h>
#include <gdk/core/Exception.h>

#if defined(__IOS__)
#	include <new>
#endif

#if defined(__JEMALLOC__)
extern "C" {
#	include <jemalloc/jemalloc.h>
}
#	if defined(_WIN32)
#	pragma comment(lib, "jemalloc.lib")
#	endif
#	define __malloc   ::je_malloc
#	define __realloc  ::je_realloc
#	define __calloc   ::je_calloc
#	define __free     ::je_free
#elif defined(__TCMALLOC__)
#	include <google/tcmalloc.h>
#	if defined(_WIN32)
#	pragma comment(lib, "libtcmalloc_minimal.lib")
#	endif
#	define __malloc   ::tc_malloc
#	define __realloc  ::tc_realloc
#	define __calloc   ::tc_calloc
#	define __free     ::tc_free
#else
#	define __malloc   ::malloc
#	define __realloc  ::realloc
#	define __calloc   ::calloc
#	define __free     ::free
#endif

#if defined(_WIN32)
#	pragma warning(disable:4985) //屏蔽编译警告, 重载 new[], VS2008编译时候出现编译警告 C4985
#endif


namespace gdk
{


#if defined(_DEBUG)

GDK_CORE_EXPORT void* malloc_(size_t nSize, int flag, const char *pFilename, int nLine, const char *pFunction);
GDK_CORE_EXPORT void  free_(void *p, int flag, const char *pFilename, int nLine, const char *pFunction);

__INLINE__ void* malloc_(size_t nSize)
{
	return malloc_(nSize, 0, 0, 0, 0);
}
__INLINE__ void  free_(void *p)
{
	return free_(p, 0, 0, 0, 0);
}

#else

GDK_CORE_EXPORT void* malloc_(size_t nSize);
GDK_CORE_EXPORT void  free_(void *p);

#endif

GDK_CORE_EXPORT void* realloc_(void* p, size_t newSize);
__INLINE__ void* calloc_(size_t numOfElements, size_t sizeOfElements)
{
	return malloc_(numOfElements * sizeOfElements);
}


//=====================================================
#if defined(_DEBUG)

extern GDK_CORE_EXPORT bool g_noDumpMemoryLeak;
extern GDK_CORE_EXPORT void enableDumpMemoryLeak(void);
extern GDK_CORE_EXPORT void disableDumpMemoryLeak(void);

#define ENABLE_gdkDumpMemoryLeak()	gdk::enableDumpMemoryLeak()
#define DISABLE_gdkDumpMemoryLeak()	gdk::disableDumpMemoryLeak()

#else

#define ENABLE_gdkDumpMemoryLeak()	((void)0)
#define DISABLE_gdkDumpMemoryLeak()	((void)0)

#endif



} //namespace gdk


#pragma push_macro("new")
#undef new


#if defined(__IOS__)

GDK_CORE_EXPORT void* __CDECL__ operator new(size_t nSize) throw(std::bad_alloc);
GDK_CORE_EXPORT void  __CDECL__ operator delete(void *p) throw();

GDK_CORE_EXPORT void* __CDECL__ operator new[](size_t nSize) throw(std::bad_alloc);
GDK_CORE_EXPORT void  __CDECL__ operator delete[](void *p) throw();

#else

__INLINE__ void* __CDECL__ operator new(size_t nSize)
{
	return gdk::malloc_(nSize);
}
__INLINE__ void  __CDECL__ operator delete(void *p)
{
	return gdk::free_(p);
}

__INLINE__ void* __CDECL__ operator new[](size_t nSize)
{
	return gdk::malloc_(nSize);
}
__INLINE__ void  __CDECL__ operator delete[](void *p)
{
	return gdk::free_(p);
}

#endif



__INLINE__ void* __CDECL__ operator new(size_t nSize, int, const char *pFilename, int nLine, const char *pFunction)
{
	(void)&nSize;
	(void)&pFilename;
	(void)&nLine;
	(void)&pFunction;

#if defined(_DEBUG)
	return gdk::malloc_(nSize, 0, pFilename, nLine, pFunction);
#else
	return gdk::malloc_(nSize);
#endif
}
__INLINE__ void  __CDECL__ operator delete(void *p, int, const char *pFilename, int nLine, const char *pFunction)
{
	(void)&p;
	(void)&pFilename;
	(void)&nLine;
	(void)&pFunction;

#if defined(_DEBUG)
	return gdk::free_(p, 0, pFilename, nLine, pFunction);
#else
	return gdk::free_(p);
#endif
}



__INLINE__ void* __CDECL__ operator new[](size_t nSize, int, const char *pFilename, int nLine, const char *pFunction)
{
	(void)&nSize;
	(void)&pFilename;
	(void)&nLine;
	(void)&pFunction;
    
#if defined(_DEBUG)
	return gdk::malloc_(nSize, 0, pFilename, nLine, pFunction);
#else
	return gdk::malloc_(nSize);
#endif
}
__INLINE__ void  __CDECL__ operator delete[](void *p, int, const char *pFilename, int nLine, const char *pFunction)
{
	(void)&p;
	(void)&pFilename;
	(void)&nLine;
	(void)&pFunction;
    
#if defined(_DEBUG)
	return gdk::free_(p, 0, pFilename, nLine, pFunction);
#else
	return gdk::free_(p);
#endif
}



__INLINE__ void* __CDECL__ operator new(size_t nSize, void *_Where, int, const char *pFilename, int nLine, const char *pFunction)
{
	(void)&nSize;
	(void)&pFilename;
	(void)&nLine;
	(void)&pFunction;

	return (_Where);
}

__INLINE__ void  __CDECL__ operator delete(void *p, void *_Where, int, const char *pFilename, int nLine, const char *pFunction)
{
	(void)&p;
	(void)&_Where;
	(void)&pFilename;
	(void)&nLine;
	(void)&pFunction;
}



__INLINE__ void* __CDECL__ operator new[](size_t nSize, void *_Where, int, const char *pFilename, int nLine, const char *pFunction)
{
	(void)&nSize;
	(void)&pFilename;
	(void)&nLine;
	(void)&pFunction;

	return (_Where);
}

__INLINE__ void  __CDECL__ operator delete[](void *p, void *_Where, int, const char *pFilename, int nLine, const char *pFunction)
{
	(void)&p;
	(void)&_Where;
	(void)&pFilename;
	(void)&nLine;
	(void)&pFunction;
}




//----------------------------------------------------
__INLINE__ void* __CDECL__ operator new(size_t nSize, const char *pFilename, int nLine)
{
	(void)&nSize;
	(void)&pFilename;
	(void)&nLine;
    
#if defined(_DEBUG)
	return gdk::malloc_(nSize, 0, pFilename, nLine, NULL);
#else
	return gdk::malloc_(nSize);
#endif
}
__INLINE__ void  __CDECL__ operator delete(void *p, const char *pFilename, int nLine)
{
	(void)&p;
	(void)&pFilename;
	(void)&nLine;
    
#if defined(_DEBUG)
	return gdk::free_(p, 0, pFilename, nLine, NULL);
#else
	return gdk::free_(p);
#endif
}



__INLINE__ void* __CDECL__ operator new[](size_t nSize, const char *pFilename, int nLine)
{
	(void)&nSize;
	(void)&pFilename;
	(void)&nLine;
    
#if defined(_DEBUG)
	return gdk::malloc_(nSize, 0, pFilename, nLine, NULL);
#else
	return gdk::malloc_(nSize);
#endif
}
__INLINE__ void  __CDECL__ operator delete[](void *p, const char *pFilename, int nLine)
{
	(void)&p;
	(void)&pFilename;
	(void)&nLine;
    
#if defined(_DEBUG)
	return gdk::free_(p, 0, pFilename, nLine, NULL);
#else
	return gdk::free_(p);
#endif
}



__INLINE__ void* __CDECL__ operator new(size_t nSize, int, const char *pFilename, int nLine)
{
	(void)&nSize;
	(void)&pFilename;
	(void)&nLine;
    
#if defined(_DEBUG)
	return gdk::malloc_(nSize, 0, pFilename, nLine, NULL);
#else
	return gdk::malloc_(nSize);
#endif
}
__INLINE__ void  __CDECL__ operator delete(void *p, int, const char *pFilename, int nLine)
{
	(void)&p;
	(void)&pFilename;
	(void)&nLine;
    
#if defined(_DEBUG)
	return gdk::free_(p, 0, pFilename, nLine, NULL);
#else
	return gdk::free_(p);
#endif
}



__INLINE__ void* __CDECL__ operator new[](size_t nSize, int, const char *pFilename, int nLine)
{
	(void)&nSize;
	(void)&pFilename;
	(void)&nLine;
    
#if defined(_DEBUG)
	return gdk::malloc_(nSize, 0, pFilename, nLine, NULL);
#else
	return gdk::malloc_(nSize);
#endif
}
__INLINE__ void  __CDECL__ operator delete[](void *p, int, const char *pFilename, int nLine)
{
	(void)&p;
	(void)&pFilename;
	(void)&nLine;
    
#if defined(_DEBUG)
	return gdk::free_(p, 0, pFilename, nLine, NULL);
#else
	return gdk::free_(p);
#endif
}
//----------------------------------------------------



#ifndef __GDK_INIT_OPERATOR_NEW__
#define __GDK_INIT_OPERATOR_NEW__

#if defined(_DEBUG)

static bool init_operator_new(void)
{
	operator delete(operator new(1));
	operator delete(operator new(1, 0, NULL, 0, NULL), 0, NULL, 0, NULL);
	operator delete(operator new(0, NULL, 0, NULL, 0, NULL), NULL, 0, NULL, 0, NULL);
	operator delete(operator new(1, NULL, 0), NULL, 0);
	operator delete(operator new(1, 0, NULL, 0), 0, NULL, 0);

	operator delete[](operator new[](1));
	operator delete[](operator new[](1, 0, NULL, 0, NULL), 0, NULL, 0, NULL);
	operator delete[](operator new[](0, NULL, 0, NULL, 0, NULL), NULL, 0, NULL, 0, NULL);
	operator delete[](operator new[](1, NULL, 0), NULL, 0);
	operator delete[](operator new[](1, 0, NULL, 0), 0, NULL, 0);

	return true;
}
static bool g_init_operator_new = init_operator_new();

#endif

#endif //__GDK_INIT_OPERATOR_NEW__

/*
__INLINE__ void* __CDECL__ operator new(size_t nSize, void *_Where)
{
	return operator new(nSize, _Where, NULL, 0);
}

__INLINE__ void __CDECL__ operator delete(void *p, void *_Where)
{
	operator delete(p, _Where, NULL, 0);
}



__INLINE__ void* __CDECL__ operator new[](size_t nSize, void *_Where)
{
	return operator new[](nSize, _Where, NULL, 0);
}

__INLINE__ void __CDECL__ operator delete[](void *p, void *_Where)
{
	operator delete[](p, _Where, NULL, 0);
}
*/


#pragma pop_macro("new")


#if defined(_DEBUG)
#	define GDK_NEW new(0, __FILE__, __LINE__, __FUNCTION__)
#else
#	define GDK_NEW new
#endif

#define GDK_DELETE delete




#endif //__GDK_NEW_H__
